﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Caching;
using DotLiquid;
using DotLiquid.FileSystems;

namespace Framework
{
    public static class TemplateHelper
    {
        #region Template路径
        #endregion
        static TemplateHelper()
        {
            TemplateConfig = new TemplateConfig();
        }

        public static TemplateConfig TemplateConfig;
        public static Dictionary<string, string> Map = new Dictionary<string, string>();
        public static bool ContainsKey(string key)
        {
            return Map.ContainsKey(key);
        }
        public static string GetTemplateUrl(string key)
        {
            try
            {
                return Map[key];
            }
            catch (KeyNotFoundException e)
            {
                var ne = new KeyNotFoundException(e.Message + "key:" + key);
                throw ne;
            }
        }
        /// <summary>
        /// 初始化
        /// </summary>
        public static void Init(Dictionary<string, string> dictionary)
        {
            lock (Map)
            {
                Map = dictionary;
            }
            Template.RegisterFilter(typeof(StandardFilters));
            Template.FileSystem = new IncludeFileSystem(Encoding.UTF8);
        }
        /// <summary>
        /// 初始化
        /// </summary>
        public static void Init()
        {
            Template.RegisterFilter(typeof(TemplateFilters));
            Template.FileSystem = new IncludeFileSystem(Encoding.UTF8);
        }
        /// <summary>
        /// 初始化
        /// </summary>
        public static void Init(Type type, IFileSystem iFileSystem)
        {
            Template.RegisterFilter(type);
            Template.FileSystem = iFileSystem;
        }
        public static void Set(Dictionary<string, string> dictionary)
        {
            lock (Map)
            {
                Map = dictionary;
            }
        }
        /*这个方法限制了文件模板路径必要配置，如果需要可以添加直接以文件路径为参数的方法，
         *不过感觉这里配置起来是个好的习惯 */
        public static Template GetFileTemplate(string templateKey, Encoding encoding)
        {
            var template = HttpContext.Current.Cache[templateKey] as Template;
            if (template == null)
            {
                string path = HttpContext.Current.Server.MapPath(GetTemplateUrl(templateKey));
                template = Template.Parse(File.ReadAllText(path, encoding));
                var dependency = new CacheDependency(path);
                HttpContext.Current.Cache.Add(templateKey, template, dependency, Cache.NoAbsoluteExpiration,
                    Cache.NoSlidingExpiration, CacheItemPriority.Default, null);//把模板缓存起来
            }
            return template;
        }
        public static Template GetFileTemplate(string templateKey)
        {
            return GetFileTemplate(templateKey, Encoding.UTF8);
        }
        public static bool GenerateSave(string templateKey, object o, string filePath)
        {
            return GenerateSave(templateKey, o, filePath, Encoding.UTF8);
        }
        public static bool GenerateSave(string templateKey, object o, string filePath, Encoding encoding)
        {
            try
            {
                //设置文件名（这里可以根据需要变化命名）
                Template template = GetFileTemplate(templateKey, encoding);
                var html = template.Render(Hash.FromAnonymousObject(o));
                var path = Path.GetDirectoryName(filePath);
                if (path != null)
                {
                    var dir = new DirectoryInfo(path);
                    if (!dir.Exists)
                        dir.Create();
                }
                using (FileStream cfs = File.Create(filePath))
                {
                    using (var sw = new StreamWriter(cfs, encoding))
                    {
                        sw.Write(html);
                        sw.Flush();
                        sw.Close();
                        sw.Dispose();
                    }
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
